﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Otonomos.Utils;

namespace Otonomos.World
{
    public class Point3D : IComparable<Point3D>, IEquatable<Point3D>
    {
        public double X { get; private set; }
        public double Y { get; private set; }
        public double Z { get; private set; }

        public static Point3D Origin = new Point3D();

        public Point3D() : this(0.0, 0.0, 0.0)
        {
        }

        public Point3D(double x, double y, double z)
        {
            X = x;
            Y = y;
            Z = z;
        }

        public double Distance(Point3D other)
        {
            return Math.Sqrt((this.X - other.X) * (this.X - other.X) +
                (this.Y - other.Y) * (this.Y - other.Y) +
                (this.Z - other.Z) * (this.Z - other.Z));
        }

        public override bool Equals(object obj)
        {
            return this.Equals(obj as Point3D);
        }

        public override string ToString()
        {
            return string.Format("({0}/{1}/{3}", X, Y, Z);
        }

        public bool Equals(Point3D other)
        {
            if (other == null)
                return false;
            return other.X == X && other.Y == Y && other.Z == Z;
        }
        
        public int CompareTo(Point3D other)
        {
            if (other.X != X)
            {
                return X.CompareTo(other.X);
            }

            if (other.Y != Y)
            {
                return Y.CompareTo(other.Y);
            }

            return Z.CompareTo(other.Z);
        }

        public static bool operator ==(Point3D a, Point3D b)
        {
            return EqualsUtility.OperatorEquals(a, b);
        }

        public static bool operator !=(Point3D a, Point3D b)
        {
            return !EqualsUtility.OperatorEquals(a, b);
        }

        public override int GetHashCode()
        {
            return X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode();
        }
    }
}
